<template>
  <el-table border ref="tableElement" :max-height="maxHeight" :data="data" style="width: 100%" @selection-change="handleSelection">
    <el-table-column type="selection" width="55" v-if="selection" fixed="left" :selectable="selectable" />
    <el-table-column v-for="item in headList" :key="item.prop" v-bind="filterHead(item)">
      <template #header>
        <div class="table-head">
          <template v-if="$slots[item.prop + 'Header']">
            <slot :name="item.prop + 'Header'"></slot>
          </template>
          <span v-else>{{ item.label }}</span>
        </div>
      </template>
      <!-- 默认插槽 -->
      <template #default="{ row, $index }">
        <template v-if="$index !== -1">
          <template v-if="!$slots[item.prop]">
            <span>{{ row[item.prop] }}</span>
          </template>
          <!-- 作用域插槽 -->
          <slot v-else :name="item.prop" :row="(row as T)" :index="$index" v-bind="item"></slot>
        </template>
      </template>
    </el-table-column>
  </el-table>
</template>

<script setup lang="ts" generic="T">
import { ref } from 'vue'

defineOptions({
  name: 'a-table'
})

interface Props {
  data: T[] // 表格数据
  head: TableHead[]
  selectable?: (data: T) => boolean
  maxHeight?: number | string
}

const tableElement = ref<TableInstance | undefined>()

const props = withDefaults(defineProps<Props>(), {
  selectable: () => {
    return true
  },
  maxHeight: 550
})

const selection = defineModel<T[]>('selection')
const headList = setTableHeadAttr(props.head)

function filterHead(h: TableHead): TableHead {
  const o = { ...h }
  delete o.children
  return o
}

function setTableHeadAttr(h: TableHead[]): TableHead[] {
  return h.map((item) => {
    if (item['show-overflow-tooltip'] === undefined) {
      item['show-overflow-tooltip'] = true
    }

    if (item.width === undefined) {
      item['min-width'] = '200px'
    }

    if (item.children && item.children.length) item.children = setTableHeadAttr(item.children)
    return item
  })
}

function handleSelection(row: T[]) {
  selection.value = row
}

defineExpose({
  element: tableElement
})
</script>

<style lang="scss">
.table-head {
  width: 100%;
  @include text-overflow;
}
</style>
